////////////////////////////////////////////////////////////////////////////
//
//  Crytek Engine Source File.
//  Copyright (C), Crytek Studios, 2010.
// -------------------------------------------------------------------------
//  File name:   ThreadBackEnd.h
//  Version:     v1.00
//  Created:     07/05/2011 by Christopher Bolte
//  Compilers:   Visual Studio.NET
// -------------------------------------------------------------------------
//  History:
////////////////////////////////////////////////////////////////////////////

#ifndef BLOCKING_BACKEND_H_
#define BLOCKING_BACKEND_H_

#include <IJobManager.h>
#include "../SPUDriver/JobStructs.h"

namespace JobManager { class CJobManager; }

namespace JobManager {
namespace BlockingBackEnd {
namespace detail {
	// stack size for each worker thread of the blocking backend
	enum {eStackSize = 32*1024 };

} // namespace detail

	// forward declarations
	class CBlockingBackEnd;

	// class to represent a worker thread for the PC backend
	class CBlockingBackEndWorkerThread: public CrySimpleThread<>
	{
		public:
//#ifdef CAFE
//      CBlockingBackEndWorkerThread(CrySemaphore &rSemaphore, JobManager::SJobQueue_BlockingBackEnd &rJobQueue, JobManager::SInfoBlock **pRegularWorkerFallbacks, uint32 nRegularWorkerThreads);
//#else
      CBlockingBackEndWorkerThread(CryFastSemaphore &rSemaphore, JobManager::SJobQueue_BlockingBackEnd &rJobQueue, JobManager::SInfoBlock **pRegularWorkerFallbacks, uint32 nRegularWorkerThreads);
//#endif
			~CBlockingBackEndWorkerThread();

			virtual void Run();
			virtual void Stop();
			
	private:
		void DoWork();
		void DoWorkProducerConsumerQueue(SInfoBlock &rInfoBlock);
		
		string																	m_sThreadName;				// name of the worker thread		
		uint32																	m_nId;								// id of the worker thread
		volatile bool														m_bStop;		
//#ifdef CAFE
//		CrySemaphore&												m_rSemaphore;
//#else
    CryFastSemaphore&												m_rSemaphore;
//#endif
		JobManager::SJobQueue_BlockingBackEnd&	m_rJobQueue;

		// members used for special blocking backend fallback handling
		JobManager::SInfoBlock**		m_pRegularWorkerFallbacks;
		uint32											m_nRegularWorkerThreads;
	};

	// the implementation of the PC backend
	// has n-worker threads which use atomic operations to pull from the job queue
	// and uses a semaphore to signal the workers if there is work requiered
	class CBlockingBackEnd : public IBackend
	{		
	public:
		CBlockingBackEnd( JobManager::SInfoBlock **pRegularWorkerFallbacks, uint32 nRegularWorkerThreads );
		virtual ~CBlockingBackEnd();

		bool Init(uint32 nSysMaxWorker);
		bool ShutDown();
		void Update(){}

		virtual JobManager::EAddJobRes AddJob( JobManager::CJobDelegator& RESTRICT_REFERENCE crJob, const uint32 cOpMode, const JobManager::TJobHandle cJobHandle, JobManager::SInfoBlock &rInfoBlock );
		
		virtual uint32 GetNumWorkerThreads() const { return 1; }

		void AddBlockingFallbackJob( JobManager::SInfoBlock* pInfoBlock, uint32 nWorkerThreadID );
	private:
		friend class JobManager::CJobManager;

		JobManager::SJobQueue_BlockingBackEnd				m_JobQueue;						// job queue node where jobs are pushed into and from
//#ifdef CAFE
//    CrySemaphore												    		m_Semaphore;	
//#else
		CryFastSemaphore														m_Semaphore;					// semaphore to count available jobs, to allow the workers to go sleeping instead of spinning when no work is requiered
//#endif
		CBlockingBackEndWorkerThread*								m_pWorkerThreads;			// worker thread for blocking backend, only one supported

		// members used for special blocking backend fallback handling
		JobManager::SInfoBlock**									m_pRegularWorkerFallbacks;
		uint32																		m_nRegularWorkerThreads;
	};

} // namespace ThreadBackEnd
} // namespace JobManager
			

#endif // BLOCKING_BACKEND_H_